/**
 * pageca.c
 * 连续内存片段管理实现
 * 
 * 竹影半墙
 * 2023.08
 */
#include "bsw_pageca.h"

static bsw_always_inline void * pca_end(bsw_pageca_s *pa)
{
    return (char*)pa->start + pa->size;
}

static bsw_always_inline uint16_t pca_size_real(bsw_memca_s *ma)
{
    return bsw_max(ma->size, sizeof(void*));
}

#if 0
#endif
void bsw_pca_init(bsw_pageca_s *pa)
{
    void *s, *e;
    uint64_t pgnr;
    uint16_t size;
    bsw_memca_s *ma;

    ma = bsw_pa_to_ma(pa);
    size = pca_size_real(ma);
    pgnr = size * ma->max / bsw_pagesize();
    ma->max -= pgnr * bsw_pagesize() / size;
    pa->size = pgnr * bsw_pagesize();

    bsw_mca_init(ma);
    if (!pgnr)
        return ;
    s = malloc(pgnr * bsw_pagesize());
    pa->page = pa->start = s;
    e = (char*)s + pgnr*bsw_pagesize();
    if (!s)
        return ;
    for (/* none */; s < e; s += size) {
        if (s + (size<<1) > e)
            break;
        *(void**)s = s + size;
    }
    *(void**)s = NULL;
    return ;
}

void bsw_pca_close(bsw_pageca_s *pa)
{
    bsw_mca_close(bsw_pa_to_ma(pa));
    free(pa->start);
    pa->page = pa->start = NULL;
    return ;
}

void * bsw_pca_alloc(bsw_pageca_s *pa)
{
    void *v;
    bsw_memca_s *ma = bsw_pa_to_ma(pa);

    v = bsw_ma_alloc(ma, &pa->page, 0);
    return v ?: bsw_mca_alloc(ma);
}

void bsw_pca_free(bsw_pageca_s *pa, void *v)
{
    bsw_memca_s *ma;
    void *end = pca_end(pa);

    ma = bsw_pa_to_ma(pa);
    if (pa->start <= v && v < end) {
        bsw_ma_free(ma, &pa->page, v, 1);
        return ;
    }
    bsw_mca_free(ma, v);
    return ;
}

void * bsw_pca_swap(bsw_pageca_s *pa, void *v)
{
    void *vp;
    bsw_memca_s *ma;
    void *end = pca_end(pa);

    if (pa->start <= v && v < end)
        return v;
    ma = bsw_pa_to_ma(pa);
    vp = bsw_ma_alloc(ma, &pa->page, 0);
    if (!vp)
        return v;
    memcpy(vp, v, ma->size);
    bsw_ma_free(ma, &ma->head, v, 1);
    return vp;
}